/*
 * MIT License
 *
 * Copyright (c) 2019 Mr.css
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
package cn.seaboot.commons.core;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;

/**
 * list -> tree 转换工具
 * <p>
 * 通过 compare()/setter() 回调的方式实现
 * <p>
 * 这个工具的好处，是直接使用原始数据进行组合；
 * <p>
 * 缺点就是：通过接口回调的方式实现，代码格式难看些；封装程度低，很多东西需要二次加工。
 *
 * @param <P> 父级
 * @param <C> 子级
 * @see cn.seaboot.commons.lang.TreeBuilder
 */
public class TreeBuilder<P, C> {
    private List<P> parent;
    private List<C> children;
    private BiFunction<P, C, Integer> compare;
    private BiConsumer<P, C> setter;

    public TreeBuilder() {
        this.children = new ArrayList<>();
        this.parent = new ArrayList<>();
    }

    /**
     * 设置父级列表
     *
     * @param parent 父级列表
     * @return TreeBuilder 实例
     */
    public TreeBuilder<P, C> setParent(List<P> parent) {
        this.parent = parent;
        return this;
    }

    /**
     * 设置子级列表
     *
     * @param children 子级列表
     * @return TreeBuilder 实例
     */
    public TreeBuilder<P, C> setChildren(List<C> children) {
        this.children = children;
        return this;
    }

    /**
     * 设置比较函数
     *
     * @param compare 比较函数
     * @return TreeBuilder 实例
     */
    public TreeBuilder<P, C> setCompare(BiFunction<P, C, Integer> compare) {
        this.compare = compare;
        return this;
    }

    /**
     * 设置setter函数
     *
     * @param setter 添加子节点的函数
     * @return TreeBuilder 实例
     */
    public TreeBuilder<P, C> setChildSetter(BiConsumer<P, C> setter) {
        this.setter = setter;
        return this;
    }

    /**
     * 数据分组
     *
     * @return TreeBuilder 实例
     */
    public TreeBuilder<P, C> groupBy() {
        if (CommonUtils.isEmpty(parent) && CommonUtils.isEmpty(children)) {
            throw new IllegalArgumentException("Child list and parent list are both empty!");
        }

        for (P p : parent) {
            for (C c : children) {
                if (this.compare.apply(p, c) == 0) {
                    setter.accept(p, c);
                }
            }
        }
        return this;
    }

    /**
     * 获取父级列表
     *
     * @return 父级列表
     */
    public List<P> getParent() {
        return parent;
    }
}